package controller

import (
	"context"

	"kstar-gf-api/app/admin/api"
	"kstar-gf-api/internal/model"
	"kstar-gf-api/internal/service"
	"kstar-gf-api/library/aliyunOss"
	"kstar-gf-api/library/snowflake"
	"kstar-gf-api/library/utils"

	"github.com/gogf/gf/v2/crypto/gmd5"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/gogf/gf/v2/util/gconv"
)

var AuthApi = authApi{}

type authApi struct{}

func (a *authApi) Login(ctx context.Context, req *api.LoginReq) (res *api.LoginRes, err error) {
	adminInfo, err := service.Admin().GetAdminInfoByPhone(ctx, req.UserPhone)
	if err != nil {
		return nil, err
	}
	if adminInfo == nil {
		return nil, gerror.New("用户名或密码错误")
	}

	userSalt := adminInfo.UserPassword[:32]
	userPassword := adminInfo.UserPassword[32:]
	if !service.Admin().VerifyPassword(userSalt+req.UserPassword, userPassword) {
		return nil, gerror.New("用户名或密码错误")
	}

	// 生成Token
	tokenId := a.GenerateTokenId("")
	err = g.RequestFromCtx(ctx).Session.SetId(tokenId)
	if err != nil {
		return nil, err
	}

	userInfo := api.UserInfo{
		TokenId:   tokenId,
		UserId:    adminInfo.UserId,
		UserName:  adminInfo.UserName,
		UserPhone: adminInfo.UserPhone,
		CreateBy:  adminInfo.CreateBy,
	}

	g.RequestFromCtx(ctx).Session.MustSetMap(gconv.Map(userInfo))

	// 获取token有效期
	sessionMaxAge := g.Server().GetSessionMaxAge()
	expireAt := gtime.Now().Add(sessionMaxAge).Timestamp()

	// 获取管理员所有的学校列表
	in := &model.GetTenantAdminListInput{
		UserId: adminInfo.UserId,
	}
	tenantAdminList, _, _ := service.TenantAdmin().GetTenantAdminList(ctx, in, 1, -1)

	resList := []*api.LoginTenantList{}
	for _, tenantAdmin := range tenantAdminList {
		resList = append(resList, &api.LoginTenantList{
			TenantId:   tenantAdmin.TenantId,
			TenantName: tenantAdmin.TenantInfo.TenantName,
			RoleIds:    tenantAdmin.RoleIds,
			RoleNames:  tenantAdmin.RoleNames,
		})
	}

	// 获取最后登录的学校信息
	lastTenant := api.LoginTenantList{}
	tenantInfo, err := service.TenantAdmin().GetLastLoginTenant(ctx, adminInfo.UserId)
	if err != nil {
		return nil, err
	}
	if tenantInfo != nil {
		lastTenant.TenantId = tenantInfo.TenantId
		lastTenant.TenantName = tenantInfo.TenantName
		lastTenant.RoleIds = tenantInfo.RoleIds
		lastTenant.RoleNames = tenantInfo.RoleNames
	}

	retInfo := api.LoginRes{
		Token:      tokenId,
		UserInfo:   userInfo,
		ExpireAt:   expireAt,
		TenantList: resList,
		LastTenant: &lastTenant,
	}

	return &retInfo, nil
}

func (a *authApi) LoginTenant(ctx context.Context, req *api.LoginTenantReq) (res *api.LoginTenantRes, err error) {
	// 查询管理员是否拥有该租户权限
	userId := gconv.String(ctx.Value("userId"))

	tenantAdmin, err := service.TenantAdmin().GetTenantAdminInfo(ctx, userId, req.TenantId)
	if err != nil {
		return nil, gerror.New("无该租户权限")
	}

	// 查询角色列表
	roleList, _, _ := service.Role().GetRoleList(ctx, &model.RoleListInput{}, 0, -1)

	roleIdArray, _ := utils.SplitAndConvert(tenantAdmin.RoleIds, ",", func(s string) (int64, error) {
		return gconv.Int64(s), nil
	})
	RoleNameArray := make([]string, 0)
	for _, role := range roleList {
		if utils.InArray(role.RoleId, roleIdArray) {
			RoleNameArray = append(RoleNameArray, role.RoleName)
		}
	}
	roleNames := utils.Implode(RoleNameArray, ",")

	tokenId := ctx.Value("tokenId").(string)

	userInfo := api.UserInfo{
		TokenId:    tokenId,
		UserId:     userId,
		TenantId:   tenantAdmin.TenantId,
		TenantName: tenantAdmin.TenantInfo.TenantName,
		RoleIds:    tenantAdmin.RoleIds,
		RoleNames:  roleNames,
		UserName:   ctx.Value("userName").(string),
		UserPhone:  ctx.Value("userPhone").(string),
		CreateBy:   ctx.Value("CreateBy").(string),
	}

	g.RequestFromCtx(ctx).Session.MustSetMap(gconv.Map(userInfo))

	retInfo := api.LoginTenantRes{
		TenantId:   tenantAdmin.TenantId,
		TenantName: tenantAdmin.TenantInfo.TenantName,
		RoleIds:    tenantAdmin.RoleIds,
		RoleNames:  roleNames,
	}

	// 更新最后登录时间
	service.TenantAdmin().UpdateLastLoginTime(ctx, userId, tenantAdmin.TenantId)

	return &retInfo, nil
}

func (a *authApi) Logout(ctx context.Context, req *api.LogoutReq) (res *api.LogoutRes, err error) {

	g.RequestFromCtx(ctx).Session.RemoveAll()

	return
}

// 生成Token
func (a *authApi) GenerateTokenId(openId string) string {
	id, _ := gmd5.Encrypt(snowflake.Generate().String())

	token := ""
	if openId != "" {
		token = "jsessionid:app:" + openId + ":" + id
	} else {
		token = "jsessionid:pc:" + id
	}
	return token
}

func (a *authApi) GetOssSignature(ctx context.Context, req *api.GetOssSignatureReq) (res *api.GetOssSignatureRes, err error) {
	ossRespond, err := aliyunOss.GetOssSignature(ctx, req.Dir)
	if err != nil {
		return
	}

	err = gconv.Scan(ossRespond, &res)

	return
}
